/*
 * 文件名：QuartzServiceImpl.java
 * 版权：Copyright by Layne
 * 描述：
 * 修改人：Layne
 * 修改时间：2019年5月24日
 * 跟踪单号：
 * 修改单号：
 * 修改内容：
 */

package top.layne.boot.samples.quartz.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.quartz.CronScheduleBuilder;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;

import top.layne.boot.samples.quartz.entity.QuartzInfo;
import top.layne.boot.samples.quartz.service.IQuartzService;

@Service
@SuppressWarnings("unchecked")
public class QuartzServiceImpl implements IQuartzService {
	private static final Logger LOGGER = LoggerFactory.getLogger(QuartzServiceImpl.class);

	@Resource
	private SchedulerFactoryBean schedulerFactoryBean;

	@Override
	public QuartzInfo insert(QuartzInfo quartzInfo) throws Exception {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();

		JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(quartzInfo.getJobClassName())).withIdentity(quartzInfo.getJobName(), quartzInfo.getJobGroupName()).build();
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzInfo.getJobName(), quartzInfo.getJobGroupName())
				.withSchedule(CronScheduleBuilder.cronSchedule(quartzInfo.getJobCronExpression())).usingJobData("cronExpression", quartzInfo.getJobCronExpression()).build();

		scheduler.scheduleJob(jobDetail, trigger);
		return quartzInfo;
	}

	@Override
	public QuartzInfo update(QuartzInfo quartzInfo) throws Exception {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey(quartzInfo.getJobName(), quartzInfo.getJobGroupName());
		Trigger trigger = scheduler.getTrigger(triggerKey);
		trigger = TriggerBuilder.newTrigger().withIdentity(quartzInfo.getJobName(), quartzInfo.getJobGroupName()).withSchedule(CronScheduleBuilder.cronSchedule(quartzInfo.getJobCronExpression()))
				.usingJobData("cronExpression", quartzInfo.getJobCronExpression()).build();
		scheduler.rescheduleJob(triggerKey, trigger);
		return quartzInfo;
	}

	@Override
	public boolean delete(QuartzInfo quartzInfo) {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		try {
			scheduler.deleteJob(JobKey.jobKey(quartzInfo.getJobName(), quartzInfo.getJobGroupName()));
		} catch (SchedulerException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	@Override
	public boolean pause(QuartzInfo quartzInfo) {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		try {
			scheduler.pauseJob(JobKey.jobKey(quartzInfo.getJobName(), quartzInfo.getJobGroupName()));
		} catch (SchedulerException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	@Override
	public boolean resume(QuartzInfo quartzInfo) {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		try {
			scheduler.resumeJob(JobKey.jobKey(quartzInfo.getJobName(), quartzInfo.getJobGroupName()));
		} catch (SchedulerException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	@Override
	public List<QuartzInfo> query() {
		List<QuartzInfo> quartzInfos = new ArrayList<>();
		QuartzInfo quartzInfo = null;
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		try {
			Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.anyGroup());
			Set<TriggerKey> triggerKeys = scheduler.getTriggerKeys(GroupMatcher.anyGroup());
			for (JobKey jobKey : jobKeys) {
				JobDetail jobDetail = scheduler.getJobDetail(jobKey);
				quartzInfo = new QuartzInfo();
				quartzInfo.setJobName(jobDetail.getKey().getName());
				quartzInfo.setJobClassName(jobDetail.getJobClass().getName());
				quartzInfo.setJobGroupName(jobDetail.getKey().getGroup());

				for (TriggerKey triggerKey : triggerKeys) {
					Trigger trigger = scheduler.getTrigger(triggerKey);
					if (StringUtils.equals(jobDetail.getKey().getName(), trigger.getKey().getName()) && StringUtils.equals(jobDetail.getKey().getGroup(), trigger.getKey().getGroup())) {
						quartzInfo.setJobCronExpression(trigger.getJobDataMap().getString("cronExpression"));
						quartzInfo.setTriggerState(scheduler.getTriggerState(triggerKey));
					}
				}
				quartzInfos.add(quartzInfo);
			}
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
		return quartzInfos;
	}

}
